package fila;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import model.Usuario;
import util.Gerador;

public class MM1 {
	
	private Double lambda;
	private Double mi;
	
	public MM1(Double lambda, Double mi) {
		this.lambda = lambda;
		this.mi = mi;
	}
	
	public List<Double> runFCFS(Integer limite) {
		List<Double> amostrasTempo = new ArrayList<Double>();
		
		Queue<Double> fila = new LinkedList<Double>();
		
        double proximaChegada = Gerador.getExponencial(this.lambda);
        double proximaSaida = Double.POSITIVE_INFINITY;
        
        while(amostrasTempo.size() < limite) {
            if (proximaChegada <= proximaSaida) {
                if (fila.isEmpty()) {
                	Double prox = Gerador.getExponencial(this.mi);
                	proximaSaida = proximaChegada + prox;
                }

                fila.add(proximaChegada);
                proximaChegada += Gerador.getExponencial(this.lambda);
            } else {
                double tempo = proximaSaida - fila.poll();
                
                amostrasTempo.add(tempo);

                if (fila.isEmpty())
                	proximaSaida = Double.POSITIVE_INFINITY;
                else {
                	Double prox = Gerador.getExponencial(this.mi);
                	proximaSaida += prox;
                }
            }
        }
        
        return amostrasTempo;
	}
	
	public List<Double> runLCFSComInterrupcaoComContinuidade(Integer limite) {
		List<Double> amostrasTempo = new ArrayList<Double>();

		List<Usuario> fila = new ArrayList<Usuario>();
		double proximaChegada = Gerador.getExponencial(this.lambda);
		double proximaSaida = Double.POSITIVE_INFINITY;
		
		while(amostrasTempo.size() < limite) {
			if (proximaChegada <= proximaSaida) {
				Double saida = Gerador.getExponencial(this.mi);
				Usuario u = new Usuario(proximaChegada, saida);
				
	            if (!fila.isEmpty()) {
	            	Usuario interrompido = fila.get(0);
	            	interrompido.setServico(proximaSaida - proximaChegada);
	            }
	            
	            proximaSaida = proximaChegada + saida;

	            fila.add(0, u);
	            proximaChegada += Gerador.getExponencial(this.lambda);
	        } else {
	        	double tempo = proximaSaida - fila.get(0).getChegada();
                
                amostrasTempo.add(tempo);
                
                fila.remove(0);

                if (fila.isEmpty())
                	proximaSaida = Double.POSITIVE_INFINITY;
                else {
                	proximaSaida += fila.get(0).getServico();
                }
	        }
			
		}
		
		return amostrasTempo;
	}

}
